﻿namespace EyeOpen.Validation.Test
{
    using System.Linq;
    using Mapping;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using SharpTestsEx;

    /// <summary>
    /// Tests the <see cref="FooValidationMapping"/> class.
    /// </summary>
    [TestClass]
    public class FooValidatorTest
    {
        private readonly FooValidationMapping fooValidationMapping;
        private readonly PropertyMap namePropertyMapped;
        private readonly IEntityValidator<FooEntity> fooValidator = new FooValidator();

        /// <summary>
        /// Initializes a new instance of the <see cref="FooValidatorTest"/> class.
        /// </summary>
        public FooValidatorTest()
        {
            fooValidationMapping = new FooValidationMapping();
            namePropertyMapped = fooValidationMapping.PropertiesMapped.ToList().Single();
        }

        /// <summary>
        /// Creates a <see cref="FooEntity"/> validation mapping expected correct properties are mapped.
        /// </summary>
        [TestMethod]
        [Owner("Matteo Migliore")]
        [Description("Unit.CodeBase.Validation.Mapping")]
        public void CreateFooValidationMappingExpectedCorrectPropertiesAreMapped()
        {       
            const string FooNamePropertyName = "Name";

            namePropertyMapped
                .PropertyName
                .Should("The property mapped for the FooEntity is not name.")
                .Be
                .EqualTo(FooNamePropertyName);
        }

        /// <summary>
        /// Creates the <see cref="FooEntity"/> validation mapping expected correct validators are mapped for name property.
        /// </summary>
        [TestMethod]
        [Owner("Matteo Migliore")]
        [Description("Unit.CodeBase.Validation.Mapping")]
        public void CreateFooValidationMappingExpectedCorrectValidatorsAreMappedForNameProperty()
        {
            var validators =
                namePropertyMapped
                    .Validators
                    .OrderBy(o => o.GetType().Name)
                    .ToList();
                                        
            validators[0]
                .GetType()
                .Should("The first validator for FooEntity is not LengthValidator.")
                .Be
                .EqualTo(typeof(MinimumLengthValidator));

            validators[1]
                .GetType()
                .Should("The second validator for FooEntity is not RequiredValidator.")
                .Be
                .EqualTo(typeof(RequiredValidator));
        }

        /// <summary>
        /// Validates the A <see cref="FooEntity"/> with <c>null</c> name expected <see cref="RequiredValidator"/> consider not valid.
        /// </summary>
        [TestMethod]
        [Owner("Matteo Migliore")]
        [Description("Unit.CodeBase.Validation.Mapping")]
        public void ValidateAFooEntityWithNullNameExpectedConsiderNotValid()
        {
            fooValidator
                .IsValid(new FooEntity())       
                .Should("Validators of FooEntity consider a not valid entity as valid.")
                .Be
                .False();

            var validationResults =
                fooValidator
                    .ValidationResults
                    .ToList();

            validationResults
                .Count
                .Should("Validation results are not right number.")
                .Be
                .EqualTo(1);

            validationResults[0]
                .PropertyName
                .Should("Wrong property name in validation result.")
                .Be
                .EqualTo("Name");

            validationResults[0]
                .ValidationMessages
                .Count
                .Should("Validation messages is not right number.")
                .Be
                .EqualTo(2);
        }

        /// <summary>
        /// Validates a <see cref="FooEntity"/> with short name expected length validator consider valid.
        /// </summary>
        [TestMethod]
        [Owner("Matteo Migliore")]
        [Description("Unit.CodeBase.Validation.Mapping")]
        public void ValidateAFooEntityWithShortNameExpectedConsideredValid()
        {
            fooValidator
                .IsValid(new FooEntity { Name = "123" })
                .Should("Validators of FooEntity consider not valid a valid entity.")
                .Be
                .True();

            var validationResults =
                fooValidator
                    .ValidationResults
                    .ToList();

            validationResults
                .Count
                .Should("Validation results are not right number.")
                .Be
                .EqualTo(0);
        }

        /// <summary>
        /// Validates a <see cref="FooEntity"/> with same name and last name expected considered not valid.
        /// </summary>
        [TestMethod]
        [Owner("Matteo Migliore")]
        [Description("Unit.CodeBase.Validation.Mapping")]
        public void ValidateAFooEntityWithSameNameAndLastNameExpectedConsideredNotValid()
        {
            fooValidator
                .IsValid(new FooEntity { Name = "a", Lastname = "A" })
                .Should("Validators of FooEntity consider valid a not valid entity.")
                .Be
                .False();

            var validationResults =
                fooValidator
                    .ValidationResults
                    .ToList();

            validationResults
                .Count
                .Should("Validation results are not right number.")
                .Be
                .EqualTo(2);
        }
    }
}